package com.wdb.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wdb.annotation.Log;
import com.wdb.domain.SysLog;
import com.wdb.mapper.SysLogMapper;
import com.wdb.service.LogService;
import com.wdb.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * @author: wendaobai@qq.com
 * @date: 2024/9/10 星期二 10:10com.wdb.annotation.Log
 */
@Service
@Slf4j
public class LogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> implements LogService {
  @Override
  public void save(
      String username, String browser, String ip, ProceedingJoinPoint joinPoint, SysLog sysLog) {
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    com.wdb.annotation.Log aopLog = method.getAnnotation(Log.class);
    String value = aopLog.value();
    // 方法路径
    String methodName =
        joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
    sysLog.setDescription(value);
    sysLog.setRequestIp(ip);
    sysLog.setAddress(StringUtils.getCityInfo(ip));
    sysLog.setMethod(methodName);
    sysLog.setUsername(username);
    sysLog.setParams(getParams(method, joinPoint.getArgs()));
    sysLog.setBrowser(browser);
    save(sysLog);
  }

  /**
   * 获取方法的参数列表
   *
   * @param method 被调用的方法对象
   * @param args 传递给方法的实际参数数组
   * @return 返回格式化后的参数字符串
   */
  private String getParams(Method method, Object[] args) {
    // 创建一个新的对象列表，用于存储处理后的参数
    ArrayList<Object> argList = Lists.newArrayList();
    // 获取方法的参数列表
    Parameter[] parameters = method.getParameters();

    // 遍历方法的参数列表
    for (int i = 0; i < parameters.length; i++) {
      // 留空待后续实现参数的处理逻辑
      if (args[i] instanceof MultipartFile) {
        continue;
      }
      // 检查是否为RequestBody类型的参数
      Parameter parameter = parameters[i];
      RequestBody requestBody = parameter.getAnnotation(RequestBody.class);
      if (requestBody != null) {
        argList.add(requestBody);
      }
      // 检查是否为RequestParam类型的参数
      RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
      if (requestParam != null) {
        HashMap<String, Object> hashMap = new HashMap<>(2);
        // 使用注解的值或者参数的名称作为键
        String key = parameter.getName();
        if (!StringUtils.isEmpty(requestParam.value())) {
          key = requestParam.value();
        }
        hashMap.put(key, args[i]);
        argList.add(hashMap);
      }
      // 除了@RequestBody 和 @RequestParam 注解的参数，其他参数直接添加到argList中
      if (requestBody == null && requestParam == null) {
        HashMap<String, Object> hashMap = new HashMap<>(2);
        // 使用注解的值或者参数的名称作为键
        String key = parameter.getName();
        hashMap.put(key, args[i]);
        argList.add(hashMap);
      }
    }
    // 日志输出方法的参数列表和实际参数数组
    // log.info("params---{}", argList);
    // 根据argList的状态返回相应的结果
    if (argList.isEmpty()) {
      return "";
    }

    // 返回处理后的参数字符串
    return argList.size() == 1 ? JSON.toJSONString(argList.get(0)) : JSON.toJSONString(argList);
  }
}
